#include once "fbgfx.bi"

type MyDot
  X as integer
  Y as integer
end type

declare function Collision(OBJA as any ptr, OAX as integer, OAY as integer, _
OBJB as any ptr, OBX as integer, OBY as integer, THEDOT as MYDOT ptr=0, USEALPHA as integer=0) as integer

function Collision(OBJA as any ptr, OAX as integer, OAY as integer, OBJB as any ptr, OBX as integer, OBY as integer,THEDOT as MYDOT ptr=0,USEALPHA as integer=0) as integer
    
  dim as integer COLLI,TX,TY,RESULT,IBPP
  dim as integer OASX,OASY,OBSX,OBSY
  dim as integer OAXX,OAYY,OBXX,OBYY
  dim as integer APIT,BPIT,XCNT,YCNT
  dim as integer AAPIT,BBPIT,COX,COY,CXY
  dim as any ptr ASTRT,BSTRT,CSTRT
  
  const MaximumAlpha = 64 'Max alpha value that will be considered transparent
  const HeaderSize = sizeof(fb.image) 'size of the image header (if any) (32 bytes for fbgfx)
  OASX = cptr(fb.image ptr,OBJA)->width-1 'width of the object A minus one
  OASY = cptr(fb.image ptr,OBJA)->height-1 'height of the object A minus one  
  OBSX = cptr(fb.image ptr,OBJB)->width-1 'width of the object B minus one
  OBSY = cptr(fb.image ptr,OBJB)->height-1 'height of the object B minus one  
  IBPP = cptr(fb.image ptr,OBJA)->BPP  'BYTES per pixel (1(8), 2(16), 4(32)
  APIT = cptr(fb.image ptr,OBJA)->PITCH 'width*BPP object A (16 byte granularity for fbgfx)
  BPIT = cptr(fb.image ptr,OBJB)->PITCH 'width*BPP object B (16 byte granularity for fbgfx) 
  AAPIT = APIT:BBPIT = BPIT
  OAXX = OAX+OASX:OAYY = OAY+OASY
  OBXX = OBX+OBSX:OBYY = OBY+OBSY  
  
  if IBPP = 1 then 
    IBPP = 0
  elseif IBPP = 2 then
    IBPP = 1
  elseif IBPP = 4 then
    IBPP = 2
  else
    return 0
  end if
  
  do    
    if OAX >= OBX and OAX <= OBXX then
      ' ********** 11 ***********
      if OAY >= OBY and OAY <= OBYY then 
        if OBXX > OAXX then TX = OAXX else TX = OBXX
        if OBYY > OAYY then TY = OAYY else TY = OBYY        
        ASTRT = OBJA + HeaderSize 
        BSTRT = OBJB + HeaderSize + _
        ((OAX-OBX) shl IBPP) + ((OAY-OBY)*BPIT)
        XCNT = (TX-OAX)+1:YCNT = (TY-OAY)+1
        APIT -= ((TX-OAX) shl IBPP)+(1 shl IBPP)
        BPIT -= ((TX-OAX) shl IBPP)+(1 shl IBPP)        
        RESULT = 11: exit do
      end if
      ' ********** >12< ***********
      if OAYY >= OBY and OAYY <= OBYY then 
        if OBXX > OAXX then TX = OAXX else TX = OBXX        
        ASTRT = OBJA + HeaderSize + ((OBY-OAY)*APIT)
        BSTRT = OBJB + HeaderSize + ((OAX-OBX) shl IBPP)
        XCNT = (TX-OAX)+1:YCNT = (OAYY-OBY)+1
        APIT -= ((TX-OAX) shl IBPP)+(1 shl IBPP)
        BPIT -= ((TX-OAX) shl IBPP)+(1 shl IBPP)        
        RESULT = 12: exit do
      end if
      ' *********** 13 *************
      if OAY <= OBY and OAYY >= OBYY then
        ASTRT = OBJA + HeaderSize + ((OBY-OAY)*APIT)
        BSTRT = OBJB + HeaderSize + ((OAX-OBX) shl IBPP)
        XCNT = (OBXX-OAX)+1:YCNT = OBSY+1
        APIT -= ((OBXX-OAX) shl IBPP)+(1 shl IBPP)
        BPIT -= ((OBXX-OAX) shl IBPP)+(1 shl IBPP)        
        RESULT = 13: exit do
      end if
    end if
    
    if OAXX >= OBX and OAXX <= OBXX then
      ' *********** <21> *************
      if OAY >= OBY and OAY <= OBYY then 
        if OBYY > OAYY then TY = OAYY else TY = OBYY        
        ASTRT = OBJA + HeaderSize + ((OBX-OAX) shl IBPP)
        BSTRT = OBJB + HeaderSize + ((OAY-OBY)*BPIT)
        XCNT = (OAXX-OBX)+1:YCNT = (TY-OAY)+1
        APIT -= ((OAXX-OBX) shl IBPP)+(1 shl IBPP)
        BPIT -= ((OAXX-OBX) shl IBPP)+(1 shl IBPP)        
        RESULT = 21: exit do
      end if
      ' *********** <22> ************
      if OAYY >= OBY and OAYY <= OBYY then
        ASTRT = OBJA + HeaderSize + _
        ((OASY-(OAYY-OBY))*APIT) + _
        ((OASX-(OAXX-OBX)) shl IBPP)
        BSTRT = OBJB + HeaderSize
        XCNT = (OAXX-OBX)+1:YCNT = (OAYY-OBY)+1
        APIT -= ((OAXX-OBX) shl IBPP)+(1 shl IBPP)
        BPIT -= ((OAXX-OBX) shl IBPP)+(1 shl IBPP)        
        RESULT = 22: exit do
        ' *********** <23> ************
      end if
      if OAY <= OBY and OAYY >= OBYY then
        ASTRT = OBJA + HeaderSize + _
        ((OBY-OAY)*APIT) + ((OBX-OAX) shl IBPP)
        BSTRT = OBJB + HeaderSize
        XCNT = (OAXX-OBX)+1:YCNT = OBSY+1
        APIT -= ((OAXX-OBX) shl IBPP)+(1 shl IBPP)
        BPIT -= ((OAXX-OBX) shl IBPP)+(1 shl IBPP)        
        RESULT = 23: exit do
      end if
    end if
    
    if OAX <= OBX and OAXX >= OBXX then
      ' ********** <31> *************
      if OAY >= OBY and OAY <= OBYY then
        ASTRT = OBJA + HeaderSize + ((OBX-OAX) shl IBPP)
        BSTRT = OBJB + HeaderSize  + ((OAY-OBY)*BPIT)
        XCNT = OBSX+1:YCNT = (OBYY-OAY)+1
        APIT -= ((OBSX) shl IBPP)+(1 shl IBPP)
        BPIT -= ((OBSX) shl IBPP)+(1 shl IBPP)        
        RESULT = 31: exit do
      end if
      ' ********** <32> *************
      if OAYY >= OBY and OAYY <= OBYY then 
        ASTRT = OBJA + HeaderSize + _
        ((OBY-OAY)*APIT) + ((OBX-OAX) shl IBPP)
        BSTRT = OBJB + HeaderSize
        XCNT = OBSX+1:YCNT = (OAYY-OBY)+1
        APIT -= ((OBSX) shl IBPP)+(1 shl IBPP)
        BPIT -= ((OBSX) shl IBPP)+(1 shl IBPP)        
        RESULT = 32: exit do
      end if
      ' ********** <33> *************
      if OAY <= OBY and OAYY >= OBYY then
        ASTRT = OBJA + HeaderSize + _
        ((OBY-OAY)*APIT) + ((OBX-OAX) shl IBPP)
        BSTRT = OBJB + HeaderSize
        XCNT = OBSX+1:YCNT = OBSY+1
        APIT -= ((OBSX) shl IBPP)+(1 shl IBPP)
        BPIT -= ((OBSX) shl IBPP)+(1 shl IBPP)        
        RESULT = 33: exit do
      end if
    end if
    return 0    
  loop 
  
  if XCNT then
    
    if THEDOT<>0 then
      COY = int((ASTRT-((OBJA+HeaderSize)))/AAPIT)
      COX = (ASTRT-((OBJA+HeaderSize)+(COY*AAPIT))) shr IBPP
    end if
    
    select case IBPP
    case 0
      ' ******** 8 bpp pixel check ******
      asm      
        mov ESI,[ASTRT]         'ESI = ObjectA intersected rect pointer
        mov EDI,[BSTRT]         'EDI = ObjectB intersected rect pointer
        mov EAX,[APIT]          'EAX = Pitch of objecta excluding intersect size
        mov EBX,[XCNT]          'EBX = width of intersect area
        mov EDX,[YCNT]          'EDX = height of intersect area
        _CPNEXTLINE8_:        'compare next 8 bit line
        mov ECX,EBX             'ECX=EBX (intersected width)
        _CPNEXTPIXEL8_:       'compare next 8 bit pixel
        cmp byte ptr [ESI],0    'pixel in object A is transparent?
        je _CPSKIPPIXEL8_       'yes? than no collision is possible (skip that pixel)
        cmp byte ptr [EDI],0    'pixel in object B is transparent?
        je _CPSKIPPIXEL8_       'yes? than no collision is possible (skip that pixel)
        mov [CSTRT],ESI
        jmp _CPENDCOLISION8_    'collision found (go to end of verification code)
        _CPSKIPPIXEL8_:       'skipped a pixel
        inc ESI                 'point obj A to the next pixel
        inc EDI                 'point obj B to the next pixel
        dec ECX                 'decrease the width counter (one pixel less)
        jnz _CPNEXTPIXEL8_      'go test next pixel until it reaches 0
        add ESI,EAX             'point obj A to the next line
        add EDI,[BPIT]          'point obj B to the next line
        dec EDX                 'decrease height counter (one line less)
        jnz _CPNEXTLINE8_       'go test next line until it reaches 0
        neg dword ptr [RESULT]  'change RESULT signal (to negative)
        _CPENDCOLISION8_:     'end of verification
      end asm
    case 1
      ' ******** 16 bpp pixel check ******
      asm      
        mov ESI,[ASTRT]             'ESI = ObjectA intersected rect pointer
        mov EDI,[BSTRT]             'EDI = ObjectB intersected rect pointer        
        mov EBX,[XCNT]              'EBX = width of intersect area
        mov EDX,[YCNT]              'EDX = height of intersect area
        mov EAX,[APIT]              'EAX = Pitch of objecta excluding intersect size
        _CPNEXTLINE16_:           'compare next 16 bit line
        mov ECX,EBX                 'ECX=EBX (intersected width)        
        _CPNEXTPIXEL16_:          'compare next 16 bit pixel        
        cmp word ptr [ESI],0xF81F   'pixel in object A is transparent?
        je _CPSKIPPIXEL16_          'yes? than no collision is possible (skip that pixel)
        cmp word ptr [EDI],0xF81F   'pixel in object B is transparent?
        je _CPSKIPPIXEL16_          'yes? than no collision is possible (skip that pixel)              
        mov [CSTRT],ESI
        jmp _CPENDCOLISION16_       'collision found (go to end of verification code)
        _CPSKIPPIXEL16_:          'skipped a pixel
        add ESI,2                   'point obj A to the next pixel
        add EDI,2                   'point obj B to the next pixel
        dec ECX                     'decrease the width counter (one pixel less)
        jnz _CPNEXTPIXEL16_         'go test next pixel until it reaches 0
        add ESI,EAX                 'point obj A to the next line       
        add EDI,[BPIT]              'point obj B to the next line
        dec EDX                     'decrease height counter (one line less)
        jnz _CPNEXTLINE16_          'go test next line until it reaches 0
        neg dword ptr [RESULT]      'change RESULT signal (to negative)
        _CPENDCOLISION16_:        'end of verification
      end asm
    case 2
      if USEALPHA then
        ' ******** 32 bpp pixel check (including alhpa) ******
        asm      
          mov ESI,[ASTRT]             'ESI = ObjectA intersected rect pointer
          mov EDI,[BSTRT]             'EDI = ObjectB intersected rect pointer        
          mov EBX,[XCNT]              'EBX = width of intersect area
          mov EDX,[YCNT]              'EDX = height of intersect area          
          _CPNEXTLINE32A_:          'compare next 32 bit line
          mov ECX,EBX                 'ECX=EBX (intersected width)        
          _CPNEXTPIXEL32A_:         'compare next 32 bit pixel        
          mov EAX,[ESI]               'EAX = Pixel in object A
          cmp EAX,0xFFFF00FF          'pixel in object A is transparent?
          je _CPSKIPPIXEL32A_         'yes? than no collision is possible (skip that pixel)
          shr EAX,24                  'Getting alpha value
          cmp AL,MaximumAlpha         'Is alpha below or equal Maximum Alpha?
          jbe _CPSKIPPIXEL32A_        'yes? than no collision is possible (skip that pixel)          
          mov EAX, [EDI]              'EAX = Pixel in object B
          cmp EAX,0xFFFF00FF          'pixel in object B is transparent?
          je _CPSKIPPIXEL32A_         'yes? than no collision is possible (skip that pixel)
          shr EAX,24                  'Getting alpha value
          cmp AL,MaximumAlpha         'Is alpha below or equal Maximum Alpha?
          jbe _CPSKIPPIXEL32A_        'yes? than no collision is possible (skip that pixel)          
          mov [CSTRT],ESI
          jmp _CPENDCOLISION32A_      'collision found (go to end of verification code)
          _CPSKIPPIXEL32A_:         'skipped a pixel
          add ESI,4                   'point obj A to the next pixel
          add EDI,4                   'point obj B to the next line
          dec ECX                     'decrease height counter (one line less)
          jnz _CPNEXTPIXEL32A_        'go test next pixel until it reaches 0
          add ESI,[APIT]              'point obj A to the next line       
          add EDI,[BPIT]              'point obj B to the next line
          dec EDX                     'decrease height counter (one line less)
          jnz _CPNEXTLINE32A_         'go test next line until it reaches 0     
          neg dword ptr [RESULT]      'change RESULT signal (to negative)
          _CPENDCOLISION32A_:       'end of verification
        end asm
      else
        ' ******** 32 bpp pixel check ******
        asm      
          mov ESI,[ASTRT]             'ESI = ObjectA intersected rect pointer
          mov EDI,[BSTRT]             'EDI = ObjectB intersected rect pointer        
          mov EBX,[XCNT]              'EBX = width of intersect area
          mov EDX,[YCNT]              'EDX = height of intersect area
          mov EAX,[APIT]              'EAX = Pitch of objecta excluding intersect size
          _CPNEXTLINE32_:             'compare next 32 bit line
          mov ECX,EBX                 'ECX=EBX (intersected width)        
          _CPNEXTPIXEL32_:          'compare next 32 bit pixel        
          cmp dword ptr [ESI],0xFFFF00FF   'pixel in object A is transparent?
          je _CPSKIPPIXEL32_          'yes? than no collision is possible (skip that pixel)
          cmp dword ptr [EDI],0xFFFF00FF   'pixel in object B is transparent?
          je _CPSKIPPIXEL32_          'yes? than no collision is possible (skip that pixel)
          mov [CSTRT],ESI
          jmp _CPENDCOLISION32_       'collision found (go to end of verification code)
          _CPSKIPPIXEL32_:          'skipped a pixel
          add ESI,4                   'point obj A to the next pixel
          add EDI,4                   'point obj B to the next line
          dec ECX                     'decrease height counter (one line less)
          jnz _CPNEXTPIXEL32_         'go test next pixel until it reaches 0
          add ESI,EAX                 'point obj A to the next line       
          add EDI,[BPIT]              'point obj B to the next line
          dec EDX                     'decrease height counter (one line less)
          jnz _CPNEXTLINE32_          'go test next line until it reaches 0     
          neg dword ptr [RESULT]      'change RESULT signal (to negative)
          _CPENDCOLISION32_:        'end of verification
        end asm    
      end if
    end select
  end if
  
  if THEDOT<>0 and RESULT>0 then
    CXY = int((CSTRT-ASTRT)/APIT)    
    THEDOT->Y = COY '+CXY
    THEDOT->X = COX+(CSTRT-(ASTRT+(CXY*APIT))) shr IBPP    
  end if
  
  return RESULT
  
end function
